package freedom.utils.enumplus;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.StringType;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.UserType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author charlie tingfangcao@163.com
 * @date 2019年12月26日 上午11:08:49
 * 
 */
public class NameEnumType implements UserType, DynamicParameterizedType {
    static Logger log = LoggerFactory.getLogger(NameEnumType.class);
	private static final int[] SQL_TYPES = { Types.VARCHAR };

	@Override
	public int[] sqlTypes() {
		return SQL_TYPES;
	}

	private Class<?> enumClass;

	@SuppressWarnings("rawtypes")
    @Override
	public Class returnedClass() {
		return enumClass;
	}

	@Override
	public void setParameterValues(Properties parameters) {
		final ParameterType reader = (ParameterType) parameters.get(PARAMETER_TYPE);
		if (reader != null) {
			Class<?> clazz = reader.getReturnedClass();
			enumClass = clazz.asSubclass(Enum.class);// 自动寻找枚举
		}
	}

	@Override
	public Object assemble(Serializable paramSerializable, Object paramObject) throws HibernateException {
		return paramSerializable;
	}

	@Override
	public Object deepCopy(Object paramObject) throws HibernateException {
		return paramObject;
	}

	@Override
	public Serializable disassemble(Object paramObject) throws HibernateException {
		return (Serializable) paramObject;
	}

	@Override
	public boolean equals(Object x, Object y) throws HibernateException {
		if (x == y)
			return true;
		if (null == x || null == y)
			return false;
		return x.equals(y);
	}

	@Override
	public int hashCode(Object paramObject) throws HibernateException {
		return paramObject.hashCode();
	}

	@Override
	public boolean isMutable() {
		return false;
	}

    @SuppressWarnings("unchecked")
    @Override
	public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
			throws HibernateException, SQLException {
		String name = (String) StringType.INSTANCE.nullSafeGet(rs, names[0], session, owner);
		log.debug("get name:{}", name);
		Object object = null;
		if (!rs.wasNull() && null != name)
			object = Enum.valueOf(this.returnedClass(), name);
		return object;
	}

	@Override
	public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
			throws HibernateException, SQLException {
		log.debug("set value:{}", value);
		if (null == value) {
			st.setNull(index, Types.VARCHAR);
		} else {
			Enum<?> a = (Enum<?>) value;
			StringType.INSTANCE.nullSafeSet(st, a.name(), index, session);
		}

	}

	@Override
	public Object replace(Object paramObject1, Object paramObject2, Object paramObject3) throws HibernateException {
		return paramObject1;
	}

}
